package com.fdl.dao.base.impl;

import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.CriteriaSpecification;
import org.springframework.util.CollectionUtils;

import com.fdl.dao.base.Dao;

/**
 * 实现分页功能 
 * @project: hb-intra
 * @Date:2010-7-29
 * @version  1.0
 * @Company: 33e9
 * @author zhangYong.huang
 */
abstract public class BaseHibernateDao extends AbstractHibernateDao implements Dao{

	/**
	 * @param entityClass
	 */
	public BaseHibernateDao(Class entityClass) {
		super(entityClass);
		// TODO Auto-generated constructor stub
	}

	public static int COUNT_MODE = 1;

	public static int SCROLL_MODE = 2;

	public static int LIST_MODE = 3;

	public static int DEFAULT_PAGE_SIZE = 20;

	/**
	 * 根据Map中过滤条件和分页参数进行分页查询.
	 * 
	 * @param filterMap
	 *            过滤条件.
	 * @param pageNo
	 *            当前页码
	 * @param pageSize
	 *            每页显示记录数.
	 */
	public Page findBy(Map filterMap, int pageNo, int pageSize) {
		return findBy(filterMap, null, pageNo, pageSize);
	}

	/**
	 * 根据Map中过滤条件,排序条件和分页参数进行分页查询.
	 * 
	 * @param filterMap
	 *            过滤条件.
	 * @param orderMap
	 *            排序条件.
	 * @param pageNo
	 *            当前页码
	 * @param pageSize
	 *            每页显示记录数.
	 */
	public Page findBy(Map filterMap, Map orderMap, int pageNo, int pageSize,
			CriteriaSetup criteriaSetup) {
		Criteria criteria = getSession().createCriteria(getEntityClass());

		if (!CollectionUtils.isEmpty(filterMap)) {
			try {
				criteriaSetup.setup(criteria, filterMap);
			} catch (Exception e) {}
		}

		if (!CollectionUtils.isEmpty(orderMap))
			sortCriteria(criteria, orderMap);

		criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);

		return pagedQuery(criteria, pageNo, pageSize);
	}

	public Page findBy(Map filterMap, Map orderMap, int pageNo, int pageSize) {
		return findBy(filterMap, orderMap, pageNo, pageSize,
				getDefaultCriteriaSetup());
	}

	/**
	 * Criteria分页查询，默认count模式
	 */
	public Page pagedQuery(Criteria criteria, int pageNo, int pageSize) {
		return pagedQuery(criteria, pageNo, pageSize, COUNT_MODE);
	}

	/**
	 * Criteria分页查询，可以指定jdbc是否支持scroll
	 */
	public Page pagedQuery(Criteria criteria, int pageNo, int pageSize, int mode) {
		return CriteriaPage.getPageInstance(criteria, pageNo, pageSize, mode);
	}

	/**
	 * HQL分页查询，默认count的方式
	 */
	public Page pagedQuery(String hql, int pageNo, int pageSize, Object[] args) {
		return pagedQuery(hql, pageNo, pageSize, COUNT_MODE, args);
	}

	/**
	 * HQL分页查询,可以指定具体的模式, 如果是Count方式,须在此层完成hsql的转换与查询。
	 */
	public Page pagedQuery(String hql, int pageNo, int pageSize, int mode,
			Object[] args) {

		Query query = getSession().createQuery(hql);
		if (args != null) {
			for (int i = 0; i < args.length; i++) {
				query.setParameter(i, args[i]);
			}
		}
		if (mode == COUNT_MODE) {
			String countQueryString = " select count (*) "
					+ removeSelect(removeOrders(hql));
			List countlist = getHibernateTemplate()
					.find(countQueryString, args);
			int totalCount = ((Integer) countlist.get(0)).intValue();
			return HqlPage.getPageInstanceByCount(query, pageNo, pageSize,
					totalCount);
		} else
			return HqlPage.getPageInstance(query, pageNo, pageSize, mode);
	}

	/**
	 * 去除select 子句，未考虑union的情况
	 */
	private static String removeSelect(String hql) {

		int beginPos = hql.toLowerCase().indexOf("from");

		return hql.substring(beginPos);
	}

	/**
	 * 去除orderby 子句
	 */
	private static String removeOrders(String hql) {

		Pattern p = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*",
				Pattern.CASE_INSENSITIVE);
		Matcher m = p.matcher(hql);
		StringBuffer sb = new StringBuffer();
		while (m.find()) {
			m.appendReplacement(sb, "");
		}
		m.appendTail(sb);
		return sb.toString();
	}

}
